C++ Tutorial

本教程并不是零基础新手教程,但是有点基础的新手确实可以看。虽然直接选择章节看是一种高效快速的阅读方法,但是如果前面说过的内容,后面就不会说太细,所以还会建议通篇大致看看。

阅读需求:

  1. 懂得如何编译运行C++代码,懂得变量命名规范,以及太过基础的知识。

  2. 明白代码中不要乱用全角字符,例如中文括号。

  3. 一颗愿意学习东西的,热情的心。

大的功能向下拆分,直到形成最小单元,再逐个实现。

第一个程序 Hello, world!

打开代码编辑器输入:

一个C++程序必须有main函数,否则会报错 Undefined symbol: _main#include <iostream> 是可选的,一个C++程序可以只有main函数,但是std命名空间(namespace)就不能使用了,它在iostream这个头文件里面。

关于头文件,在C语言中,头文件会写上扩展名,例如 stdio.h , string.h 等等。但是在C++中,头文件的扩展名被省略了,在古老的C++版本中,例如一个1987年的C++编译器,里面使用 iostream.h ,也就是旧式C++。来自C语言的头文件(转换后的C)前面会加个C,例如来自C语言的 math.h 在C++中变成了 cmath 。C++新式风格是没有头文件扩展名了。

C中头文件扩展名五花八门,有hxx、hpp,或者h,最后ANSI/ISO委员会觉得太乱套了,最后一致同意不使用任何扩展名。

main函数

main函数又叫做主函数。 int main(void) {xxx; return 0;} 是main()函数,其中 int main(void) 叫做函数头,后面的 {xxx; return 0;} 叫做函数体。

int (数据类型) 表示main函数的返回类型是整数类型(integer),return 0; 表示函数的返回值是0. (void) 表明函数不接受任何参数,括号中写的是函数接受的参数,void在英文中的解释是“空的”、“空白的”、“空虚感”。

如果想让函数接受浮点数(数据类型叫做float,可以理解为小数,因计算机中处理浮点数的方式得名“浮点”),并且函数的名字叫做fun,接受的参数是一个整数类型 int ,参数的名字叫做num,返回值是1,代码如下:

再举两个例子:

C++ 11新标准:

这是显式表示不定义参数,表示禁止调用该函数。

C++注释

用两个斜线,后面一个空格表示注释。双斜线后面的代码(Code)都不会被执行,直到换行。

例如下面的程序:

第一行 (int a, int b) 表示这个函数接受两个参数,注意看这两个参数中间用逗号连接。

注释可以用来标记解释代码中的功能,写程序要养成写注释的好习惯,免得你以后看自己以前的代码,或者在公司里你的同事看你的代码一头雾水。

第三行 a=a+1 是一个“赋值运算”。对,它是一种运算。这句代码的等号就是赋值运算符,在赋值运算中,优先计算赋值运算符右侧的内容,也就是 a+1 ,然后轮到左侧,a 增大1的结果被赋值给 a 本身,所以 a 的熟知被增大1. 例如调用函数(函数英文叫做function,我在下面简单介绍)的时候

函数(function),function在英文中是功能的意思,也就是函数可以实现一个功能。一个很推荐的程序设计思想叫做“模块化”、“结构化编程”,大的功能向下拆分,直到形成最小单元,再逐个实现。

上面展示的函数的作用和它的名字一样,“加”(plus)。调用函数的时候给函数塞两个整数参数进去,它就能返回相加的结果。

result 的结果会是3.

还记得小学学的字母表示数吗?你还可以这样调用:

不知不觉说多了,更多内容在函数章节细讲。

C++ 语句

C++有很多种语句,函数也是语句,前面还说过赋值语句,下面说一下声明变量。

变量是给一块内存空间取的名字,用来存储和操作数据。这块空间有多大和变量类型有关,不同操作系统不同编译器上变量类型占用空间可能有差别。MS-DOS Turbo C++ 3.0上的char是1字节(byte)。1Byte=1/1024KB,B, KB, MB, GB, TB都是这个换算规律。

举例几个合规的变量名:使用有意义的、以小写字母开头的单词组合,单词间可用下划线分隔或驼峰式命名,避免使用保留关键字(例如int、char、void和return等)和数字开头。关键字是C++专用的词语,不能用做其他用途,你不能把int作为函数名,也不能把void作为变量名。

变量要有类型,没有一个默认的数据,程序只会给它分配一个空闲的数据块,但是不保证里面是空的,可能有其他程序或者内容留下的垃圾内容,所以你在读取它之前应该赋值,或者给它一个默认值。给予默认值的操作叫做“初始化”。在C++中变量在使用之前需要先声明,其他语言例如Python不需要这样做,使用前需要先声明这个机制好就好在你不会因为笔误不小心造一个变量出来,而且自己还看不出来,例如下面的BASIC代码:

上面的代码意图是把值为34的变量CastleDark增加MoreGhosts,然后输出MoreGhosts的数值。然而第二行不小心写错个字母,一眼看上去还看不出来,这样CastleDark的值永远是34。

实际第二行做的工作是新建个变量CastleDank,给它加上MoreGhosts。CastleDark的值还是34,没有被修改。

看下面代码演示变量相关操作。

如果你想知道不初始化直接读取变量会发生什么,请看下面程序:

我在 macOS Tahoe 26.1 操作系统上,Xcode 26.1.1 (17B100) 集成开发环境,Apple clang version 17.0.0 (clang-1700.4.4.1) 编译器,得到的结果如下:

可以看出这确实是个杂乱无章的数值。

函数

函数用于创建C++程序的模块,与面向对象编程有关,高级内容后面细说。

函数接受和传入返回值的方法前面“C++注释”章节已经说过了一些,下面再用例子演示函数多个参数的传入:

运行结果:

如果你在主函数(main函数)里面加上 using namespace std; 代码会报错,因为std名称空间中有同名的、也叫plus的内容,这引起了冲突。如果非要使用这个代码,就要把plus函数换个别的名字,例如 plus1

第二个例子:

运行结果:

你可能会疑惑,上面的代码中为什么多个地方在使用 str 这个名字,这样是否会导致冲突?

其实并不会,C和C++有“作用域”的概念,作用域就是程序中变量/标识符的有效区域,决定了在哪里可以访问它。下面用几个例子讲解:

局部作用域(函数内):

块作用域:

如果你把变量/标识符放在任何块和局部作用域外面,那就是全局变量:

命名空间作用域:

using namespace std; 引入了命名空间std,如果直接使用plus,程序会报错 No viable constructor or deduction guide for deduction of template arguments of 'plus' ,因为std中有叫做plus的东西了,准确说这个“东西”是函数对象类,它是这么用的 std::plus<int> add; ,虽然不是个函数,却占用了plus这个名字。这时候名称空间就发挥了作用,我们自己定义的plus是个函数,被我们放在mysapce命名空间里面,我们使用的时候用 myspace::plus(xxx) 就能调用plus函数,而且不引起冲突,因为myspace里面只有一个叫做plus的东西。

基础变量

前面简单提过一点变量(Variable)的事情,它被分配到内存上的一块空间,我们使用变量名来向这块空间中存储数据,或者读取其中的数据。

在实际项目中变量名最好用有意义的名字,尽量不要用 avar1ffff 这种名字,result 甚至 jie_guo 都好很多,配合上注释,能快速清晰的了解程序。

整数类型、字符类型

整数类型有 short, int, long, long long 四种,int 适合多数情况的数字存储。C++确保这些类型的最小长度,short至少16位,int 至少和 short 一样长,long 至少32位,至少与 int 一样长,long long 至少64位,至少与 long 一样长。

字符类型是 char ,可以存储一个ASCII字符,ASCII字符都有什么可以自己上网查询,里面包括字母、常见特殊符号。

整数类型和字符类型的运用示例代码如下:

不管是整数类型还是浮点类型、字符类型(char),都有一个最大值,我们可以查看一些符号常量来得知。看下面代码:

变量的位数是有最大限度的,它总共就那么长,想表示正负数就肯定损失最大值,例如short类型范围可能(不同编译器和操作系统上可能有区别)是-32767到+32767,无符号的short就能表示0到65535,想让变量无符号,只需要在前面加个 unsigned .

变量不初始化(赋值),数值是不确定的,这个前面代码演示过。

char 不光能存储字符,还能存储数字,或者说 char 在存储字符的时候本来就是存储了一个字符对应的ASCII或者UTF8码。例如你要存储256色图像,就可以声明一个 unsigned char 类型的数组(Array,有顺序的存储一个或多个同一个类型的数据)来存储图像。

有些字符不是显示出来的,而是起到辅助作用的,例如换行符号,下面代码演示了换行符的作用:

程序输出结果如下:

换行符几乎是最常用的符号之一,振铃BEL在现在的设备上不一定有用,如果你用的是一些Linux发行版的默认虚拟终端或者macOS系统虚拟终端,在执行程序的时候通常可以听到提示音或者窗口闪烁。问号一般不需要转义,直接用就行,反斜杠、单引号、双引号都有特殊的作用,转义符号、包装字符、包装字符串,所以如果你想把这些字符显示出来,就需要转义它们。

上面代码可以看到换行符号、转义后的单双引号发挥了作用,下表列举了一些特殊符号的ASCII符号、十六进制ASCII码对应关系:

Char nameASCII characterC++ codeHEX ASCII code
换行符NL(LF)\n0xA
水平制表符HT\t0x9
垂直制表符VT\v0xB
退格BS\b0x8
回车CR\r0xD
振铃BEL\a0x7
反斜杠\\\0x5C
问号?\?0x3F
单引号'\'0x27
双引号"\"0x22

浮点数类型

C++总共两种浮点数表示方法,一种是普通的小数表示法,另一种是中学学过的科学计数法。

科学计数法:数字开头可以正号负号或者省略,E后面是10的几次方,E的前后都没有空格,E的后面的数字可以有正号、负号或者省略(等同于正号)。

物理学上也经常使用科学计数法,例如电子质量是9.11e-31kg,物理学上写作9.11 * 10^31(我写公式要启用LaTeX支持,所以直接用计算器的风格写了,应该能看懂)。

 

复合类型